

#ifndef __LENGTH_OUTPUT__
#define __LENGTH_OUTPUT__

#include <vector>
#include <algorithm>
#include <iostream>
#include "Unit.h"
#include "LengthOutput.h"
#include "LengthUnit.h"


template<class UnitType>
class OutPut
{
public:
	virtual void printLength(ostream& os, Amount length) = 0;
};

template <class UnitType>
class OutPutInBase:public OutPut<UnitType>
{
public:
	void printLength(ostream& os, Amount length);
	static OutPut<UnitType> * getInstance();
	static OutPut<UnitType> * theInstancePtr;
};

template <class UnitType>
class OutPutInSeq:public OutPut<UnitType>
{
public:
	void printLength(ostream& os, Amount length);
	static OutPut<UnitType> * getInstance();
	static OutPut<UnitType> * theInstancePtr;
};




//////////////////////////////////////////////////////////////////////
// Construction/Destruction
/////////////////////////////////////////////////////////////////////
template <class UnitType>
OutPut<UnitType>* OutPutInBase<UnitType>::theInstancePtr = NULL;

template <class UnitType>
OutPut<UnitType>* OutPutInSeq<UnitType>::theInstancePtr = NULL;

template <class UnitType>
OutPut<UnitType> * OutPutInBase<UnitType>::getInstance()
{
	if (theInstancePtr == NULL)
	{
		theInstancePtr = new OutPutInBase<UnitType>;
	}
	return theInstancePtr;
}

template <class UnitType>
void OutPutInBase<UnitType>::printLength(ostream& os, Amount length)
{
       os << length << UnitType::getBaseUnit()->getUnitName();
}

template <class UnitType>
void OutPutInSeq<UnitType>::printLength(ostream& os, Amount length)
{
	if (length == 0)
	{
        	os << length << UnitType::getBaseUnit();
	}
	else
	{
		Amount tempLen = length;
		Unit::UnitVector seq = UnitType::getUnitSeq();
		for (Unit::UnitVector::const_iterator iter = seq.begin(); iter!=seq.end(); iter++)
		{
			if ((*iter)->convertFromUnit(tempLen) != 0)
			{
				os << ((*iter)->convertFromUnit(tempLen));
				os << ((*iter)->getUnitName());
			}
			tempLen = (*iter)->calremainder(tempLen);
		}
	}
}

template <class UnitType>
OutPut<UnitType> * OutPutInSeq<UnitType>::getInstance()
{
	if (theInstancePtr == NULL)
	{
		theInstancePtr = new OutPutInSeq;
	}	
	return theInstancePtr;
}

#endif 

